using System;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using LiteTools.constants.enums;
using LiteTools.tools;
using Sunny.UI;

namespace LiteTools.forms
{
    public partial class TlvNodeEditor : UIForm
    {
        private readonly TreeNode _treeNode;
        private TlvTypeEnum thisType;

        public TlvNodeEditor()
        {
            thisType = TlvTypeEnum.Unkown;
            _treeNode = new TreeNode();
            InitializeComponent();
            complete.Enabled = false;
            tag_tips.ForeColor = Color.Black;
            tag_tips.Text = "输入之后按【Enter】或者【Tab】按键，仅数据合法才能继续操作！";
            value_tips.ForeColor = Color.Black;
            value_tips.Text = "输入之后按【Enter】或者【Tab】按键，需根据Tag数据决定此输入框是否可以输入数据！";
            value_data.Enabled = false;
        }

        public TlvNodeEditor(TreeNode treeNode)
        {
            _treeNode = treeNode;
            InitializeComponent();
            tag_tips.ForeColor = Color.Black;
            value_tips.ForeColor = Color.Black;
            tag_data.Text = treeNode.Name;
            tag_data.Enabled = true;
            tag_tips.Text += GetTips(TlvUtil.GetTag(treeNode.Name, out var left, out var classEnum, out var typeEnum),
                left, classEnum, typeEnum);
            thisType = typeEnum;
            if (treeNode.Tag != null && !string.IsNullOrEmpty(treeNode.Tag.ToString()))
            {
                value_data.Text = treeNode.Tag.ToString();
                value_data.Enabled = true;
                complete.Enabled = true;
            }
            else
            {
                value_data.Enabled = false;
            }
            tag_tips.Text += "请注意，修改节点不允许修改节点的类型!";
            value_tips.Text += "输入之后按【Enter】或者【Tab】按键，需根据Tag数据决定此输入框是否可以输入数据！";
        }

        public TreeNode GetResultTlvNode()
        {
            return _treeNode;
        }

        private void tag_data_Leave(object sender, EventArgs e)
        {
            if (thisType != TlvTypeEnum.Unkown)
            {
                TlvUtil.GetTag(tag_data.Text, out var left, out var classEnum, out var typeEnum);
                if (typeEnum == thisType) return;
                UIMessageTip.ShowError(tag_data, "不允许改变节点的类型！",1500,true);
                complete.Enabled = false;
                return;
            }

            CheckTag();
        }

        private void CheckTag()
        {
            try
            {
                tag_tips.Text = GetTips(TlvUtil.GetTag(tag_data.Text, out var leftData, out var classEnum,
                    out var typeEnum), leftData, classEnum, typeEnum);
            }
            catch (Exception e)
            {
                UIMessageTip.ShowError(tag_data,
                    e.GetBaseException() is ArgumentOutOfRangeException
                        ? "读取Tag数据越界，可能是Tag数据首字节指示为多字节但提供的数据不全，请核实后重试"
                        : "识别Tag数据错误，请核实后重试", 1500, true);
                complete.Enabled = false;
            }
        }

        private string GetTips(string tag2Check, string leftData, TlvClassEnum classEnum, TlvTypeEnum typeEnum)
        {
            var tips = new StringBuilder();
            if (!string.IsNullOrEmpty(leftData))
            {
                tag_tips.ForeColor = Color.Crimson;
                tips.Append("识别到Tag为：" + tag2Check + "，但输入的Tag可能不正确，存在多余的数据：" + leftData);
            }
            else
            {
                tag_tips.ForeColor = Color.Black;
                tips.Append("识别到Tag为：" + tag2Check);
            }

            switch (classEnum)
            {
                case TlvClassEnum.Normal:
                    tips.Append(";一个常规BER-TLV");
                    break;
                case TlvClassEnum.Application:
                    tips.Append(";这是一个应用专用TLV;");
                    break;
                case TlvClassEnum.Private:
                    tips.Append(";这是一个私有格式TLV;");
                    break;
                case TlvClassEnum.Specific:
                    tips.Append(";这是一个规范定义的TLV;");
                    break;
                default:
                    tips.Append(";这是一个未知的TLV;");
                    break;
            }

            switch (typeEnum)
            {
                case TlvTypeEnum.Primitive:
                    tips.Append("TLV数据应为简单数据。");
                    value_data.Enabled = true;
                    value_tips.ForeColor = Color.Black;
                    value_tips.Text = string.Empty;
                    break;
                case TlvTypeEnum.Constructed:
                    tips.Append("TLV数据应为子TLV结构。");
                    complete.Enabled = true;
                    value_data.Enabled = false;
                    value_tips.ForeColor = Color.Crimson;
                    value_tips.Text = "识别到添加的TLV子节点是一个结构化TLV，无法直接添加节点数据，请直接完成，然后在此节点上添加新的子节点";
                    break;
                default:
                    tips.Append("TLV数据未知。");
                    value_data.Enabled = true;
                    value_tips.ForeColor = Color.Red;
                    value_tips.Text = string.Empty;
                    break;
            }

            return tips.ToString();
        }

        private void value_data_Leave(object sender, EventArgs e)
        {
            CheckValue();
        }

        private void CheckValue()
        {
            var length = value_data.Text.Trim().Length;
            if (length % 2 != 0)
            {
                UIMessageTip.ShowError(tag_data, "请提供完整字节的数据！", 1500, true);
                complete.Enabled = false;
                return;
            }

            value_tips.Text = "TLV子节点的数据长度为：" + length / 2 + "，16进制表示为：" + NumberUtils.GetHexStr(length / 2);
            complete.Enabled = true;
        }

        private void cancel_Click(object sender, EventArgs e)
        {
            DialogResult = DialogResult.Cancel;
            Close();
        }

        private void complete_Click(object sender, EventArgs e)
        {
            _treeNode.Name = tag_data.Text;
            _treeNode.Tag = value_data.Text.Trim();
            DialogResult = DialogResult.OK;
            Close();
        }

        private void tag_data_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.KeyCode == Keys.Enter || e.KeyCode == Keys.Tab)
            {
                CheckTag();
            }
        }

        private void value_data_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.KeyCode == Keys.Enter || e.KeyCode == Keys.Tab)
            {
                CheckValue();
            }
        }
    }
}